package catalina.container;

import catalina.connection.Request;
import catalina.connection.Response;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;

public class StandardContext extends ContainerBase {

    private ContextClassLoader contextClassLoader;

    private String appPath;

    @Override
    public void initInternal() {
        Properties properties = getProperties();
        if (properties == null) {
            return;
        }
        File contextFile = (File) properties.get("contextFile");
        parseContext(contextFile);
    }

    private void parseContext(File contextFile) {
        if (contextFile.isDirectory()) {
            File[] files = contextFile.listFiles();
            for (File file : files) {
                parseContext(file);
            }
        } else {
            if (contextFile.getName().equals("web.xml")) {
                parseWebXml(contextFile);
            }
        }
    }

    @Override
    public void startInternal() {

    }

    @Override
    public void stopInternal() {

    }

    @Override
    public void destroyInternal() {

    }

    @Override
    public void service(Request request, Response response) {
        String wrapperName = request.getMapper().getWrapperName();
        if (isStaticResource(wrapperName)) {
            response.outputHtml(this.appPath + "\\" + wrapperName.substring(1));
            return;
        }
        Container wrapper = findChild(wrapperName);
        if (wrapper != null) {
            wrapper.service(request, response);
        }
    }

    public boolean isStaticResource(String contextName) {
        return contextName.endsWith(".html") || contextName.endsWith(".js") ||
                contextName.endsWith(".css") || contextName.endsWith(".jpg");
    }

    /**
     * 加载解析web.xml，初始化Servlet
     */
    private void parseWebXml(File file) {
        buildClassLoader(file);
        SAXReader saxReader = new SAXReader();
        try {
            InputStream resourceAsStream = new FileInputStream(file);
            Document document = saxReader.read(resourceAsStream);
            Element rootElement = document.getRootElement();
            List<Element> selectNodes = rootElement.selectNodes("//servlet");
            for (int i = 0; i < selectNodes.size(); i++) {
                Element element = selectNodes.get(i);
                // <servlet-name>lagou</servlet-name>
                Element servletnameElement = (Element) element.selectSingleNode("servlet-name");
                String servletName = servletnameElement.getStringValue();
                // <servlet-class>server.LagouServlet</servlet-class>
                Element servletclassElement = (Element) element.selectSingleNode("servlet-class");
                String servletClass = servletclassElement.getStringValue();
                // 根据servlet-name的值找到url-pattern
                Element servletMapping = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");
                // /lagou
                String urlPattern = servletMapping.selectSingleNode("url-pattern").getStringValue();
                // 通过类加载器来加载对应的class对象
                Class<?> aClass = this.contextClassLoader.findClass(servletClass);
                Object servlet = aClass.newInstance(); // 实例化
                Container wrapperContainer = new StandardWrapper();
                wrapperContainer.setName(urlPattern);
                Properties properties = new Properties();
                properties.put("servlet", servlet);
                wrapperContainer.setProperties(properties);
                wrapperContainer.setParent(this);
                addChild(wrapperContainer);
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }  catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    private void buildClassLoader(File file) {
        int i1 = file.getAbsolutePath().indexOf("web.xml");
        this.appPath = file.getAbsolutePath().substring(0, i1);
        this.contextClassLoader = new ContextClassLoader(this.appPath + "classes\\");
    }
}
